package model

import (
	"fmt"

	"github.com/jinzhu/gorm"
)

type ArtificialCheckedStc struct {
	TP        uint32 `gorm:"TP" json:"TP"`
	FN        uint32 `gorm:"FN" json:"FN"`
	FP        uint32 `gorm:"FP" json:"FP"`
	TN        uint32 `gorm:"TN" json:"TN"`
	FPCountAv uint32 `json:"FPCountAv"`
	TNCount   uint32 `json:"TNCount"`
	FPCount   uint32 `json:"FPCount"`
}
type stcCountRet struct {
	PositiveCount uint32 `gorm:"Column:positiveCount" json:"positiveCount"`
	NegativeCount uint32 `gorm:"Column:negativeCount" json:"negativeCount"`
}

type HeartAttificialCheckedStc struct {
	Data [7][7]int `json:"data"`
}

type HeartAttificialCheckedStc2 struct {
	ErrorWithin5      uint32  `json:"errorWithin5"`
	ErrorWithin10     uint32  `json:"errorWithin10"`
	ErrorWithin15     uint32  `json:"errorWithin15"`
	ErrorExceeds15    uint32  `json:"errorExceeds15"`
	CheckedCount      uint32  `json:"checkedCount"`
	QualificationRate float32 `json:"qualificationRate"`
}

type HeartAttificialCheckedStcSwagger2 struct {
	*SwaggerSuccess
	Data *HeartAttificialCheckedStc2 `json:"data"`
}

type HeartAttificialStatData struct {
	PatientId   int     `gorm:"Column:patientId" json:"patientId"`
	Si          int     `gorm:"Column:si" json:"si"`
	Ei          int     `gorm:"Column:ei" json:"ei"`
	ChamberType int     `gorm:"Column:chamberType" json:"chamberType"`
	LVEF        float32 `gorm:"Column:LVEF" json:"LVEF"`
	LVEFSimpson float32 `gorm:"Column:LVEFSimpson" json:"LVEFSimpson"`
}

type ArtData struct {
	PatientId         int    `gorm:"Column:patientId" json:"patientId"`
	VerificationScore string `gorm:"Column:verificationScore" json:"verificationScore"`
}

type ArtificialCheckedDetail struct {
	*Model
	CheckedId           string `gorm:"Column:check_id" json:"checkedId"`
	CheckedTime         string `gorm:"Column:checkedTime" json:"checkedTime"`
	CheckedType         string `gorm:"Column:checkedType" json:"checkedType"`
	OrganType           int    `gorm:"Column:organType" json:"organType"`
	FileName            string `json:"fileName"`
	CheckedResult       string `gorm:"Column:checkedResult" json:"checkedResult"`
	Desc                string `gorm:"Column:verificationRemark" json:"verificationRemark"`
	PositiveCount       int    `gorm:"Column:positiveCount" json:"positiveCount"`
	NegativeCount       int    `gorm:"Column:negativeCount" json:"negativeCount"`
	PositiveFrozenCount int    `gorm:"Column:positiveFrozenCount" json:"positiveFrozenCount"`
	NegativeFrozenCount int    `gorm:"Column:negativeFrozenCount" json:"negativeFrozenCount"`
}

type PatientRecord struct {
	*Model
	OrganType int    `gorm:"Column:organType" json:"organType"`
	FileNames string `gorm:"Column:fileName" json:"fileName"`
	FileType  string `gorm:"Column:fileType" json:"fileType"`
}

type ArtificialCheckedDetailSwagger struct {
	*SwaggerSuccess
	Data []*ArtificialCheckedDetail `json:"data"`
}

func GetThyroidArtiStatistics(db *gorm.DB, beginTime, endTime string) (*ArtificialCheckedStc, error) {
	var stc *ArtificialCheckedStc = new(ArtificialCheckedStc)
	var timeQuery string
	if beginTime != "" && endTime != "" {
		timeQuery = fmt.Sprintf("and t1.createTime >= '%v' and t1.createTime <= '%v' ", beginTime, endTime)
	}
	var artTPData []*ArtData
	var query = "SELECT t1.patientId, t1.verificationScore from t_organ_info t1 left join t_tubercle_info t2 on t1.patientId = t2.patientId "
	query += "WHERE t1.verificationScore IS NOT NULL and t1.verificationScore != '0' and t1.organType = 0 and t2.isDelete = 0 "
	if timeQuery != "" {
		query += timeQuery
	}
	query += "group by t1.patientId,t1.verificationScore"

	res := db.Raw(query).Scan(&artTPData)
	if res.Error != nil {
		return nil, res.Error
	}
	stc.TP = uint32(len(artTPData))

	var artFPData []*ArtData
	query = "SELECT t1.patientId, t1.verificationScore from t_organ_info t1 "
	query += "WHERE t1.verificationScore IS NOT NULL and t1.verificationScore = '0' and t1.organType = 0 and t1.positiveCount > 0 "
	if timeQuery != "" {
		query += timeQuery
	}
	query += "group by t1.patientId,t1.verificationScore"
	res = db.Raw(query).Scan(&artFPData)
	if res.Error != nil {
		return nil, res.Error
	}
	stc.FP = uint32(len(artFPData))

	var artAllData []*ArtData
	query = "SELECT t1.patientId, t1.verificationScore from t_organ_info t1 "
	query += "WHERE t1.verificationScore IS NOT NULL and t1.organType = 0 "
	if timeQuery != "" {
		query += timeQuery
	}
	res = db.Raw(query).Scan(&artAllData)
	if res.Error != nil {
		return nil, res.Error
	}

	//清除TP
	artAllData = removeStatData(artTPData, artAllData)
	//清除FP
	artAllData = removeStatData(artFPData, artAllData)
	//计算TN&FN
	stc.TN, stc.FN = getTNFNValue(artAllData, "0")

	var stcCounts []*stcCountRet
	query = "SELECT t1.positiveCount, t1.negativeCount from t_organ_info t1 where t1.verificationScore = '0' and t1.organType = 0 "
	if timeQuery != "" {
		query += timeQuery
	}
	res = db.Raw(query).Scan(&stcCounts)
	if res.Error != nil {
		return nil, res.Error
	}
	if len(stcCounts) > 0 {
		for _, v := range stcCounts {
			fmt.Println("positiveCounts: ", v.PositiveCount)
			fmt.Println("negativeCounts: ", v.NegativeCount)
			stc.FPCount += v.PositiveCount
			stc.TNCount += v.NegativeCount
		}
		stc.FPCountAv = stc.FPCount / uint32(len(stcCounts))
	}

	return stc, nil
}

func GetBreastArtiStatistics(db *gorm.DB, beginTime, endTime string) (*ArtificialCheckedStc, error) {
	var stc *ArtificialCheckedStc = new(ArtificialCheckedStc)
	var timeQuery string
	if beginTime != "" && endTime != "" {
		timeQuery = fmt.Sprintf("and t1.createTime >= '%v' and t1.createTime <= '%v' ", beginTime, endTime)
	}

	var artTPData []*ArtData
	var query = "SELECT t1.patientId, t1.verificationScore from t_organ_info t1 left join t_breast_tubercle_info t2 on t1.patientId = t2.patientId "
	query += "WHERE t1.verificationScore IS NOT NULL and t1.verificationScore != '0' and t2.isDelete=0 and t1.organType=1 "
	if timeQuery != "" {
		query += timeQuery
	}
	query += "group by t2.patientId,t1.verificationScore"

	res := db.Raw(query).Scan(&artTPData)
	if res.Error != nil {
		return nil, res.Error
	}
	stc.TP = uint32(len(artTPData))

	var artAllData []*ArtData
	query = "SELECT t1.patientId, t1.verificationScore from t_organ_info t1 "
	query += "WHERE t1.verificationScore IS NOT NULL and t1.organType = 1 "
	if timeQuery != "" {
		query += timeQuery
	}
	res = db.Raw(query).Scan(&artAllData)
	if res.Error != nil {
		return nil, res.Error
	}

	var artFPData []*ArtData
	query = "SELECT t1.patientId, t1.verificationScore from t_organ_info t1 "
	query += "WHERE t1.verificationScore IS NOT NULL and t1.verificationScore = '0' and t1.positiveCount > 0 and t1.organType=1 "
	if timeQuery != "" {
		query += timeQuery
	}
	query += "group by t1.patientId,t1.verificationScore"
	res = db.Raw(query).Scan(&artFPData)
	if res.Error != nil {
		return nil, res.Error
	}
	stc.FP = uint32(len(artFPData))

	//清除TP
	artAllData = removeStatData(artTPData, artAllData)
	//清除FP
	artAllData = removeStatData(artFPData, artAllData)
	//计算TN&FN
	stc.TN, stc.FN = getTNFNValue(artAllData, "0")

	var stcCounts []*stcCountRet
	query = "SELECT t1.positiveCount, t1.negativeCount from t_organ_info t1 where t1.verificationScore = '0' and t1.organType = 1 "
	if timeQuery != "" {
		query += timeQuery
	}
	res = db.Raw(query).Scan(&stcCounts)
	if res.Error != nil {
		return nil, res.Error
	}
	if len(stcCounts) > 0 {
		for _, v := range stcCounts {
			stc.FPCount += v.PositiveCount
			stc.TNCount += v.NegativeCount
		}
		stc.FPCountAv = stc.FPCount / uint32(len(stcCounts))
	}

	return stc, nil
}

func GetCarotidArtiStatistics(db *gorm.DB, beginTime, endTime string) (*ArtificialCheckedStc, error) {
	var stc *ArtificialCheckedStc = new(ArtificialCheckedStc)
	var timeQuery string
	if beginTime != "" && endTime != "" {
		timeQuery = fmt.Sprintf("and t1.createTime >= '%v' and t1.createTime <= '%v' ", beginTime, endTime)
	}

	var artTPData []*ArtData
	var query = "SELECT t1.patientId,t1.verificationScore from t_organ_info t1 left join t_plaque_info t2 on t1.patientId = t2.patientId "
	query += "WHERE t1.verificationScore IS NOT NULL and t1.verificationScore != '未见斑块' and t1.organType = 5 and t2.createTime IS NOT NULL and t2.isDelete = 0 "
	if timeQuery != "" {
		query += timeQuery
	}
	query += "group by t1.patientId,t1.verificationScore"

	res := db.Raw(query).Scan(&artTPData)
	if res.Error != nil {
		return nil, res.Error
	}
	stc.TP = uint32(len(artTPData))

	var artFPData []*ArtData
	query = "SELECT t1.patientId,t1.verificationScore from t_organ_info t1 "
	query += "WHERE t1.verificationScore IS NOT NULL and t1.verificationScore = '未见斑块' and t1.organType = 5 and t1.positiveCount > 0 "
	if timeQuery != "" {
		query += timeQuery
	}
	query += "group by t1.patientId,t1.verificationScore"
	res = db.Raw(query).Scan(&artFPData)
	if res.Error != nil {
		return nil, res.Error
	}
	stc.FP = uint32(len(artFPData))

	var artAllData []*ArtData
	query = "SELECT t1.patientId, t1.verificationScore from t_organ_info t1 "
	query += "WHERE t1.verificationScore IS NOT NULL and t1.organType = 5 "
	if timeQuery != "" {
		query += timeQuery
	}
	res = db.Raw(query).Scan(&artAllData)
	if res.Error != nil {
		return nil, res.Error
	}

	//清除TP
	artAllData = removeStatData(artTPData, artAllData)
	//清除FP
	artAllData = removeStatData(artFPData, artAllData)
	//计算TN&FN
	stc.TN, stc.FN = getTNFNValue(artAllData, "未见斑块")

	var stcCounts []*stcCountRet
	query = "SELECT t1.positiveCount, t1.negativeCount from t_organ_info t1 where t1.verificationScore = '未见斑块' and t1.organType = 5 "
	if timeQuery != "" {
		query += timeQuery
	}
	res = db.Raw(query).Scan(&stcCounts)
	if res.Error != nil {
		return nil, res.Error
	}
	if len(stcCounts) > 0 {
		for _, v := range stcCounts {
			stc.FPCount += v.PositiveCount
			stc.TNCount += v.NegativeCount
		}
		stc.FPCountAv = stc.FPCount / uint32(len(stcCounts))
	}

	return stc, nil
}

func GetHeartArtiStatistics(db *gorm.DB, beginTime, endTime string) ([]*HeartAttificialStatData, error) {
	var timeQuery string
	if beginTime != "" && endTime != "" {
		timeQuery = fmt.Sprintf("and t1.createTime >= '%v' and t1.createTime <= '%v' ", beginTime, endTime)
	}
	var query = "select t1.patientId, LEFT(SUBSTRING_INDEX(t1.verificationScore, '～', 1), LENGTH(SUBSTRING_INDEX(t1.verificationScore, '～', 1) - 1)) as si, "
	query += "LEFT(SUBSTRING_INDEX(t1.verificationScore, '～', -1), LENGTH(SUBSTRING_INDEX(t1.verificationScore, '～', -1) - 1)) as ei, t2.chamberType, t2.LVEF, t2.LVEFSimpson "
	query += "from t_organ_info t1 left join t_cardiac_info t2 on t1.patientId = t2.patientId "
	query += "where t1.organType = 2 and t1.verificationScore is not null and t2.LVEF is not null "
	if timeQuery != "" {
		query += timeQuery
	}
	query += "order by t1.patientId asc"

	var data []*HeartAttificialStatData
	res := db.Raw(query).Scan(&data)
	if res.Error != nil {
		return nil, res.Error
	}
	return data, nil
}

// 快速复核的LVEF值由区间变为了单个值
func GetHeartArtiStatistics2(db *gorm.DB, beginTime, endTime string) ([]*HeartAttificialStatData, error) {
	var timeQuery string
	if beginTime != "" && endTime != "" {
		timeQuery = fmt.Sprintf("and t1.createTime >= '%v' and t1.createTime <= '%v' ", beginTime, endTime)
	}
	var query = "select t1.patientId, LEFT(t1.verificationScore, LENGTH(t1.verificationScore) - 1) as si, "
	query += "t2.chamberType, t2.LVEF, t2.LVEFSimpson "
	query += "from t_organ_info t1 left join t_cardiac_info t2 on t1.patientId = t2.patientId "
	query += "where t1.organType = 2 and t1.verificationScore is not null and t2.LVEF is not null "
	if timeQuery != "" {
		query += timeQuery
	}
	query += "order by t1.patientId asc"

	var data []*HeartAttificialStatData
	res := db.Raw(query).Scan(&data)
	if res.Error != nil {
		return nil, res.Error
	}
	return data, nil
}

func removeStatData(arrInput, arrOutput []*ArtData) []*ArtData {
	for _, v := range arrInput {
		for i := 0; i < len(arrOutput); {
			if v.PatientId == arrOutput[i].PatientId {
				arrOutput = append(arrOutput[:i], arrOutput[i+1:]...)
			} else {
				i++
			}
		}
	}
	return arrOutput
}

func getTNFNValue(arrInput []*ArtData, negValue string) (uint32, uint32) {
	TN := uint32(0)
	FN := uint32(0)
	for _, v := range arrInput {
		if v.VerificationScore == negValue {
			TN += 1
		} else {
			FN += 1
		}
	}
	return TN, FN
}

func GetArtiStatisticsDetail(db *gorm.DB, beginTime, endTime string) ([]*ArtificialCheckedDetail, error) {
	var timeQuery string
	if beginTime != "" && endTime != "" {
		timeQuery = fmt.Sprintf("and t1.createDateTime >= '%v' and t1.createDateTime <= '%v' ", beginTime, endTime)
	}
	var query = "select t1.id, t1.check_id, DATE_FORMAT(t1.createDateTime, '%Y-%m-%d %H:%i:%s') as checkedTime, t2.organName as checkedType, t2.verificationRemark, "
	query += "IFNULL(concat(t2.verificationGrade, ':', t2.verificationScore), t2.verificationScore) as checkedResult, t2.organType, t2.positiveCount, t2.negativeCount, t2.positiveFrozenCount, t2.negativeFrozenCount "
	query += "from t_patient_info t1 left join t_organ_info t2 on t1.id = t2.patientId "
	query += "where t2.organType is not null and t2.verificationScore is not null and t1.isDelete = 0 "
	if timeQuery != "" {
		query += timeQuery
	}
	query += "order by t1.id asc"

	var data []*ArtificialCheckedDetail
	res := db.Raw(query).Scan(&data)
	if res.Error != nil {
		return nil, res.Error
	}
	return data, nil
}

func GetPatientRecordName(db *gorm.DB, beginTime, endTime string) ([]*PatientRecord, error) {
	var timeQuery string
	if beginTime != "" && endTime != "" {
		timeQuery = fmt.Sprintf("and t1.createDateTime >= '%v' and t1.createDateTime <= '%v' ", beginTime, endTime)
	}
	var query = "select t1.id, SUBSTRING_INDEX(t3.imageName, '/', -1) as fileName, SUBSTRING_INDEX(t3.imageName, '/', -4) as fileType, t2.organType "
	query += "from t_patient_info t1 left join t_organ_info t2 on t1.id = t2.patientId left join t_image_info t3 on t1.id = t3.patientId and t2.patientId = t3.patientId "
	query += "where t2.organType is not null and t2.verificationScore is not null and t1.isDelete = 0 and t3.imageType = 15 "
	if timeQuery != "" {
		query += timeQuery
	}
	query += "order by t1.id asc"

	var data []*PatientRecord
	res := db.Raw(query).Scan(&data)
	if res.Error != nil {
		return nil, res.Error
	}
	return data, nil
}
